package com.wiiss.common.utils.bean;

import com.wiiss.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import uk.co.jemos.podam.api.PodamFactory;
import uk.co.jemos.podam.api.PodamFactoryImpl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Bean 工具类
 *
 * @author my
 */
public class BeanUtils extends org.springframework.beans.BeanUtils {

    private static final Logger log = LoggerFactory.getLogger(BeanUtils.class);

    /**
     * Bean属性复制工具方法。
     *
     * @param dest 目标对象
     * @param src  源对象
     */
    public static void copyBeanProp(Object dest, Object src) {
        try {
            copyProperties(src, dest);
        } catch (Exception e) {
            log.error("copyBeanProp error", e);
        }
    }

    public static Field findField(Class<?> clazz, String name) {
        try {
            return clazz.getField(name);
        } catch (NoSuchFieldException ex) {
            return findDeclaredField(clazz, name);
        }
    }

    public static Field findDeclaredField(Class<?> clazz, String name) {
        try {
            return clazz.getDeclaredField(name);
        } catch (NoSuchFieldException ex) {
            if (clazz.getSuperclass() != null) {
                return findDeclaredField(clazz.getSuperclass(), name);
            }
            return null;
        }
    }

    public static Object getProperty(Object obj, String name) throws NoSuchFieldException {
        Object value = null;
        Field field = findField(obj.getClass(), name);
        if (field == null) {
            throw new NoSuchFieldException("no such field [" + name + "]");
        }
        boolean accessible = field.isAccessible();
        field.setAccessible(true);
        try {
            value = field.get(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        field.setAccessible(accessible);
        return value;
    }

    /**
     * 获得父类集合，包含当前class
     *
     * @param clazz
     * @return
     */
    public static List<Class<?>> getSuperclassList(Class<?> clazz) {
        List<Class<?>> clazzes = new ArrayList<Class<?>>(3);
        clazzes.add(clazz);
        clazz = clazz.getSuperclass();
        while (clazz != null) {
            clazzes.add(clazz);
            clazz = clazz.getSuperclass();
        }
        return Collections.unmodifiableList(clazzes);
    }

    /**
     * 获取本类及其父类的字段属性
     *
     * @param clazz 当前类对象
     * @return 字段数组
     */
    public static Field[] getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        return fieldList.toArray(fields);
    }

    /**
     * 将对象中的null设置为""
     */
    public static void fillNullField(Object vo) {

        // 获取实体类的所有属性，返回Field数组
        Field[] field = getAllFields(vo.getClass());
        // 获取属性的名字
        for (Field item : field) {
            //可访问私有变量
            item.setAccessible(true);
            // 获取属性的名字
            String name = item.getName();
            if ("serialVersionUID".equals(name)) {
                continue;
            }
            // 获取属性类型
            String type = item.getGenericType().toString();
            // 将属性的首字母大写
            name = name.replaceFirst(name.substring(0, 1), name.substring(0, 1)
                    .toUpperCase());
            try {
                if (type.equals("class java.lang.String")) {
                    // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = vo.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    String value = (String) m.invoke(vo);
                    if (StringUtils.isEmpty(value)) {
                        //给属性设值
                        item.set(vo, item.getType().getConstructor(item.getType()).newInstance(""));
                    }
                } else if (type.equals("int") || "class java.lang.Integer".equals(type)) {
                    // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = vo.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    Object value = m.invoke(vo);
                    if (value == null) {
                        //给属性设值
                        item.set(vo, 0);
                    }
                } else if (type.equals("float") || "class java.lang.Float".equals(type)) {
                    // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = vo.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    Object value = m.invoke(vo);
                    if (value == null) {
                        //给属性设值
                        item.set(vo, 0F);
                    }
                } else if (type.equals("long") || "class java.lang.Long".equals(type)) {
                    // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = vo.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    Object value = m.invoke(vo);
                    if (value == null) {
                        //给属性设值
                        item.set(vo, 0L);
                    }
                } else if (type.equals("boolean") || "class java.lang.Boolean".equals(type)) {
                    // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = vo.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    Object value = m.invoke(vo);
                    if (value == null) {
                        //给属性设值
                        item.set(vo, false);
                    }
                } else if (type.contains("java.util.List")) {
                    Method m = vo.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    List list = (List) m.invoke(vo);
                    if (!CollectionUtils.isEmpty(list)) {
                        for (Object o : list) {
                            fillNullField(o);
                        }
                    }

                } else {
                    // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = vo.getClass().getMethod("get" + name);
                    // 调用getter方法获取属性值
                    Object value = m.invoke(vo);
                    if (value != null) {
                        fillNullField(value);
                    }
                }
            } catch (Exception e) {
                log.error("fillNullField error", e);
            }
        }
    }

    /**
     * 对象转化为Map
     *
     * @param obj
     * @return
     * @throws Exception
     */
    public static Map<String, String> objectToMap(Object obj) throws Exception {
        if (obj == null) {
            return null;
        }
        Map<String, String> map = new HashMap<String, String>();

        Field[] declaredFields = obj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            map.put(field.getName(), (String) field.get(obj));
        }

        return map;
    }

}
